home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 24
/
Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso
/
Aminet
/
comm
/
mail
/
Mutt089src.lha
/
Mutt-0.89i-AMIGA
/
src
/
browser.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-01-28
|
16KB
|
652 lines
/*
* Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "mutt.h"
#include "mutt_curses.h"
#include "mutt_menu.h"
#include "buffy.h"
#include "sort.h"
#include "mailbox.h"
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <pwd.h>
#include <grp.h>
/* HP-UX and ConvexOS don't have this macro */
#ifndef S_ISLNK
#define S_ISLNK(x) (((x) & S_IFMT) == S_IFLNK ? 1 : 0)
#endif
struct folder_file
{
mode_t mode;
time_t mtime;
off_t size;
char *name;
char *desc;
};
struct browser_state
{
struct folder_file *entry;
short entrylen; /* number of real entries */
short entrymax; /* max entry */
};
static char LastDir[_POSIX_PATH_MAX] = "";
/* Frees up the memory allocated for the local-global variables. */
static void destroy_state (struct browser_state *state)
{
int c;
for (c = 0; c < state->entrylen; c++)
{
safe_free ((void **) &((state->entry)[c].name));
safe_free ((void **) &((state->entry)[c].desc));
}
safe_free ((void **) &state->entry);
}
static int browser_compare_subject (const void *a, const void *b)
{
struct folder_file *pa = (struct folder_file *) a;
struct folder_file *pb = (struct folder_file *) b;
int r = strcmp (pa->name, pb->name);
return ((BrowserSort & SORT_REVERSE) ? -r : r);
}
static int browser_compare_date (const void *a, const void *b)
{
struct folder_file *pa = (struct folder_file *) a;
struct folder_file *pb = (struct folder_file *) b;
int r = pa->mtime - pb->mtime;
return ((BrowserSort & SORT_REVERSE) ? -r : r);
}
static int browser_compare_size (const void *a, const void *b)
{
struct folder_file *pa = (struct folder_file *) a;
struct folder_file *pb = (struct folder_file *) b;
int r = pa->size - pb->size;
return ((BrowserSort & SORT_REVERSE) ? -r : r);
}
static void browser_sort (struct browser_state *state)
{
int (*f) (const void *, const void *);
switch (BrowserSort & SORT_MASK)
{
case SORT_ORDER:
return;
case SORT_DATE:
f = browser_compare_date;
break;
case SORT_SIZE:
f = browser_compare_size;
break;
case SORT_SUBJECT:
default:
f = browser_compare_subject;
break;
}
qsort (state->entry, state->entrylen, sizeof (struct folder_file), f);
}
static int link_is_dir (const char *path)
{
struct stat st;
if (stat (path, &st) == 0)
return (S_ISDIR (st.st_mode));
else
return (-1);
}
static void add_folder (MUTTMENU *m, struct browser_state *state,
const char *name, const struct stat *s, int new)
{
char buffer[_POSIX_PATH_MAX + SHORT_STRING];
struct passwd *pw;
struct group *gr;
char date[16];
char *fmt;
time_t tnow;
pw = getpwuid (s->st_uid);
gr = getgrgid (s->st_gid);
tnow = time (NULL);
fmt = tnow - s->st_mtime < 31536000 ? "%b %d %H:%M" : "%b %d %Y";
strftime (date, sizeof (date), fmt, localtime (&s->st_mtime));
snprintf (buffer, sizeof (buffer), "%c %c%c%c%c%c%c%c%c%c%c %2d %-8.8s %-8.8s %8ld %s %s%s",
new ? 'N' : ' ',
S_ISDIR(s->st_mode) ? 'd' : (S_ISLNK(s->st_mode) ? 'l' : '-'),
(s->st_mode & S_IRUSR) != 0 ? 'r': '-',
(s->st_mode & S_IWUSR) != 0 ? 'w' : '-',
(s->st_mode & S_ISUID) != 0 ? 's' : (s->st_mode & S_IXUSR) != 0 ? 'x': '-',
(s->st_mode & S_IRGRP) != 0 ? 'r' : '-',
(s->st_mode & S_IWGRP) != 0 ? 'w' : '-',
(s->st_mode & S_ISGID) != 0 ? 's' : (s->st_mode & S_IXGRP) != 0 ? 'x': '-',
(s->st_mode & S_IROTH) != 0 ? 'r' : '-',
(s->st_mode & S_IWOTH) != 0 ? 'w' : '-',
(s->st_mode & S_ISVTX) != 0 ? 't' : (s->st_mode & S_IXOTH) != 0 ? 'x': '-',
s->st_nlink,
pw ? pw->pw_name : "(null)",
gr ? gr->gr_name : "(null)",
(long) s->st_size,
date,
name,
S_ISLNK (s->st_mode) ? "@" : (S_ISDIR (s->st_mode) ? "/" : ((s->st_mode & S_IXUSR) != 0 ? "*" : "")));
if (state->entrylen == state->entrymax)
{
/* need to allocate more space */
safe_realloc ((void **) &state->entry,
sizeof (struct folder_file) * (state->entrymax += 256));
if (m)
m->data = state->entry;
}
(state->entry)[state->entrylen].mode = s->st_mode;
(state->entry)[state->entrylen].mtime = s->st_mtime;
(state->entry)[state->entrylen].size = s->st_size;
(state->entry)[state->entrylen].name = safe_strdup (name);
(state->entry)[state->entrylen].desc = safe_strdup (buffer);
(state->entrylen)++;
}
static void init_state (struct browser_state *state, MUTTMENU *menu)
{
state->entrylen = 0;
state->entrymax = 256;
state->entry = (struct folder_file *) safe_malloc (sizeof (struct folder_file) * state->entrymax);
if (menu)
menu->data = state->entry;
}
static int examine_directory (MUTTMENU *menu, struct browser_state *state,
const char *d, const char *prefix)
{
struct stat s;
DIR *dp;
struct dirent *de;
char buffer[_POSIX_PATH_MAX + SHORT_STRING];
BUFFY *tmp;
if (stat (d, &s) == -1)
{
mutt_perror (d);
return (-1);
}
if (!S_ISDIR (s.st_mode))
{
mutt_error ("%s is not a directory", d);
return (-1);
}
mutt_buffy_check ();
if ((dp = opendir (d)) == NULL)
{
mutt_perror (d);
return (-1);
}
init_state (state, menu);
while ((de = readdir (dp)) != NULL)
{
if (strcmp (de->d_name, ".") == 0)
continue; /* we don't need . */
if (prefix && *prefix && strncmp (prefix, de->d_name, strlen (prefix)) != 0)
continue;
if (regexec (Mask.rx, de->d_name, 0, NULL, 0) != 0)
continue;
snprintf (buffer, sizeof (buffer), "%s/%s", d, de->d_name);
if (lstat (buffer, &s) == -1)
continue;
if ((! S_ISREG (s.st_mode)) && (! S_ISDIR (s.st_mode)) &&
(! S_ISLNK (s.st_mode)))
continue;
tmp = Incoming;
while (tmp && strcmp (buffer, tmp->path))
tmp = tmp->next;
add_folder (menu, state, de->d_name, &s, (tmp) ? tmp->new : 0);
}
closedir (dp);
browser_sort (state);
return 0;
}
static int examine_mailboxes (MUTTMENU *menu, struct browser_state *state)
{
struct stat s;
char buffer[LONG_STRING];
BUFFY *tmp = Incoming;
if (!Incoming)
return (-1);
mutt_buffy_check();
init_state (state, menu);
do
{
if (lstat (tmp->path, &s) == -1)
continue;
if ((! S_ISREG (s.st_mode)) && (! S_ISDIR (s.st_mode)) &&
(! S_ISLNK (s.st_mode)))
continue;
strfcpy (buffer, tmp->path, sizeof (buffer));
mutt_pretty_mailbox (buffer);
add_folder (menu, state, buffer, &s, tmp->new);
}
while ((tmp = tmp->next));
browser_sort (state);
return 0;
}
int select_file_search (MUTTMENU *menu, regex_t *re, int n)
{
return (regexec (re, ((struct folder_file *) menu->data)[n].name, 0, NULL, 0));
}
void folder_entry (char *s, size_t slen, MUTTMENU *menu, int num)
{
snprintf (s, slen, "%2d %s", num + 1, ((struct folder_file *) menu->data)[num].desc);
}
static void init_menu (struct browser_state *state, MUTTMENU *menu, char *title,
size_t titlelen, int buffy)
{
char path[_POSIX_PATH_MAX];
menu->current = 0;
menu->top = 0;
menu->max = state->entrylen;
if (buffy)
snprintf (title, titlelen, "Mailboxes [%d]", mutt_buffy_check ());
else
{
strfcpy (path, LastDir, sizeof (path));
mutt_pretty_mailbox (path);
snprintf (title, titlelen, "Directory [%s], File mask: %s",
path, Mask.pattern);
}
menu->redr